// import 'package:flutter_ffmpeg/flutter_ffmpeg.dart';
import 'package:cave_flutter/utils/whl_permission_util.dart';
import 'package:audio_session/audio_session.dart';
import 'package:flutter_sound/flutter_sound.dart';
import 'package:path_provider/path_provider.dart';
import 'dart:io';
import 'dart:async';
import 'dart:core';

typedef PlayStatusCallBack = Function(int status);

typedef TimeCallBack = Function(int time);

class WhlRecordVoiceUtils {
  FlutterSoundRecorder? recorderModule;
  StreamSubscription? recorderSubscription;

  // final FlutterFFmpeg ffmpeg = FlutterFFmpeg();

  FlutterSoundPlayer? playerModule;

  Codec myCodec = Codec.aacMP4;

  String filePath = "";
  int audioTime = 0;

  initRecord() async {
    recorderModule = FlutterSoundRecorder();
    playerModule = FlutterSoundPlayer();
    await recorderModule!.openRecorder();
    await playerModule!.openPlayer();
    //
    final session = await AudioSession.instance;
    await session.configure(AudioSessionConfiguration(
      avAudioSessionCategory: AVAudioSessionCategory.playAndRecord,
      avAudioSessionCategoryOptions: AVAudioSessionCategoryOptions.allowBluetooth | AVAudioSessionCategoryOptions.defaultToSpeaker,
      avAudioSessionMode: AVAudioSessionMode.spokenAudio,
      avAudioSessionRouteSharingPolicy: AVAudioSessionRouteSharingPolicy.defaultPolicy,
      avAudioSessionSetActiveOptions: AVAudioSessionSetActiveOptions.none,
      androidAudioAttributes: const AndroidAudioAttributes(
        contentType: AndroidAudioContentType.speech,
        flags: AndroidAudioFlags.none,
        usage: AndroidAudioUsage.voiceCommunication,
      ),
      androidAudioFocusGainType: AndroidAudioFocusGainType.gain,
      androidWillPauseWhenDucked: true,
    ));
    await recorderModule!.setSubscriptionDuration(const Duration(milliseconds: 10));
  }

  ///
  void start(TimeCallBack callBack) async {
    WhlPermissionUtil.reqMicrophonePermission(onSuccessAction: () async {
      try {
        Directory tempDir = await getTemporaryDirectory();
        var time = DateTime.now().millisecondsSinceEpoch;
        print("index == ${myCodec.index}");
        String path = '${tempDir.path}/$time${ext[myCodec.index]}';
        filePath = path;
        await recorderModule!.startRecorder(
          toFile: path,
          codec: myCodec,
          sampleRate: 44100,
          bitRate: 128000,
          numChannels: 2,
        );

        /// 监听录音
        recorderSubscription = recorderModule!.onProgress!.listen((e) {
          audioTime = e.duration.inSeconds;
          if (callBack != null) {
            callBack(e.duration.inSeconds);
          }
        });
      } catch (err) {
        print("pppppp");
        print(err);
      }
    });
  }

  ///
  Future<void> stopRecord({Function(RecordVoiceModel)? onSuccess}) async {
    try {
      await recorderModule!.stopRecorder().then((value) async {
        cancelSubscription();
        bool hasFile = await fileExists(filePath);
        File file = File(filePath);
        if (hasFile) {
          RecordVoiceModel voiceModel = RecordVoiceModel(filePath, audioTime, size: file.lengthSync());
          onSuccess?.call(voiceModel);
          print("has file");
        } else {
          RecordVoiceModel voiceModel = RecordVoiceModel(filePath, audioTime, status: -1);
          onSuccess?.call(voiceModel);
          print("no file");
        }
        // conversionMp3();
      });
    } catch (err) {}
    ;
  }

  // conversionMp3() async {
  //   String oldPath = filePath;
  //   String newPath = filePath.replaceAll(ext[myCodec.index], ".mp3");
  //   int result = await ffmpeg.execute('-i $oldPath -codec:a libmp3lame $newPath');
  //   if (result == 0) {
  //     print("success");
  //     filePath = newPath;
  //     File(oldPath).delete();
  //     bool hasFile = await fileExists(filePath);
  //     if (hasFile) {
  //       RecordVoiceModel voiceModel = RecordVoiceModel(filePath, audioTime);
  //       EventBusUtils.getInstance().eventBus.fire(voiceModel);
  //       print("has file");
  //     } else {
  //       RecordVoiceModel voiceModel = RecordVoiceModel(filePath, audioTime, status: -1);
  //       EventBusUtils.getInstance().eventBus.fire(voiceModel);
  //       print("no file");
  //     }
  //   } else {
  //     RecordVoiceModel voiceModel = RecordVoiceModel(filePath, 0, status: -1);
  //     EventBusUtils.getInstance().eventBus.fire(voiceModel);
  //     print("fail");
  //   }
  // }

  cancelSubscription() {
    if (recorderSubscription != null) {
      recorderSubscription!.cancel();
      recorderSubscription = null;
    }
  }

  Future<bool> fileExists(String path) async {
    return await File(path).exists();
  }

  startPlayer(String path, PlayStatusCallBack callBack, {Codec? codec}) async {
    print('音频地址-----------------');
    print(path);
    print(playerModule);
    
    try {
      if (playerModule!.isPlaying) {
        playerModule!.stopPlayer();
      }
      if (path.contains('http')) {
        await playerModule!.startPlayer(
            fromURI: path,
            codec: Codec.aacMP4,
            numChannels: 2,
            sampleRate: 44100,
            whenFinished: () {
              stopPlayer();
              if (callBack != null) {
                callBack(0);
              }
            });
      } else {
        if (await fileExists(path)) {
          await playerModule!.startPlayer(
              fromURI: path,
              codec: codec ?? Codec.aacMP4,
              numChannels: 2,
              sampleRate: 44100,
              whenFinished: () {
                stopPlayer();
                if (callBack != null) {
                  callBack(0);
                }
              });
        } else {
          if (callBack != null) {
            print("no file");
            callBack(1);
          }
        }
      }
    } catch (err) {
      print(err);
      if (callBack != null) {
        callBack(-1);
      }
    }
  }

  stopPlayer() async {
    try {
      await playerModule!.stopPlayer();
    } catch (err) {}
  }

  close() {
    if (recorderSubscription != null) {
      recorderSubscription!.cancel();
      recorderSubscription = null;
    }
    recorderModule!.closeRecorder();
    recorderModule = null;
    playerModule!.closePlayer();
    playerModule = null;
  }
}

class RecordVoiceModel {
  String path = "";
  int size = 0;
  int time = 0;
  int status = 0; //0 录制正常 -1 异常
  int uploadStatus = 0; //0 未上传  1 上传成功 2 上传失败
  String url = "";
  RecordVoiceModel(this.path, this.time, {this.status = 0, this.size = 0});
}
